package com.xjy.rpc.proxy.cglib;

import com.xjy.rpc.bean.BeanDefinition;
import com.xjy.rpc.cache.ChannelCache;
import com.xjy.rpc.cache.RpcRequestCache;
import com.xjy.rpc.config.Constant;
import com.xjy.rpc.config.RpcProperties;
import com.xjy.rpc.netty.RpcEventLoop;
import com.xjy.rpc.netty.message.RpcRequest;
import com.xjy.rpc.netty.message.RpcMessage;
import com.xjy.rpc.netty.message.RpcResponse;
import com.xjy.rpc.netty.promise.RpcFuture;
import com.xjy.rpc.register.IRegisterService;
import com.xjy.rpc.register.RpcRegisterFactory;
import com.xjy.rpc.utils.SocketParamUtils;
import io.netty.channel.Channel;
import io.netty.channel.DefaultEventLoop;
import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.Promise;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @description: TODO cglib代理callback方法 使用其自带的Enhancer生成代理
 * @author XJY
 * @date 2024/9/30 9:23
 * @version 1.0
 */
@Slf4j
public class CglibProxy implements MethodInterceptor {

    private final Object target;

    public CglibProxy(Object o){
        this.target = o;
    }


    RpcProperties rpcProperties = RpcProperties.getInstance();


    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        RpcMessage rpcMessage = new RpcMessage();
        rpcMessage.setRequestId(RpcRequestCache.getRequestId());
        rpcMessage.setMessageType(Constant.MESSAGE_TYPE_REQ);
        //TODO 这个后续可从接口获取
        rpcMessage.setExpireTime(3000);
        rpcMessage.setUnit(TimeUnit.SECONDS);
        RpcRequest body = new RpcRequest();
        IRegisterService registerService = RpcRegisterFactory.getBean("redis");
        BeanDefinition bean = registerService.discovery(rpcProperties.getServiceName(), method.getName());
        if (bean == null){
            throw new RuntimeException("BeanDefinition from Redis is null");
        }
        body.setIp(bean.getIp());
        body.setPort(bean.getPort());
        body.setInterfaceName(bean.getClassName());
        body.setMethodName(bean.getMethodName());
        body.setMethodResponseType(bean.getReturnType().getName());
        body.setRequestId(rpcMessage.getRequestId());
        rpcMessage.setBody(body);
        //TODO 这里需要缓存netty连接channel
        Channel channel = ChannelCache.channelMap.get(
                SocketParamUtils.getKeyByIp(bean.getIp(),bean.getPort())
        );
        if (channel == null){
            throw new RuntimeException("socketChannel from cache is null");
        }
        channel.writeAndFlush(rpcMessage);
        //处理接口调用时间
        RpcFuture<RpcResponse> rpcFuture = new RpcFuture(new DefaultPromise(new RpcEventLoop()));
        //缓存
        RpcRequestCache.REQUEST_MAP.put(rpcMessage.getRequestId(),rpcFuture);
        RpcResponse rpcResponse = rpcFuture.getPromise().sync().get();
        if (rpcResponse.getException() != null){
            return rpcResponse.getException();
        }
        return rpcResponse.getResult();
    }
}
